package boundary;

import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.ButtonGroup;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import store.Termine;
import store.Terminologia;
import dataview.CriterioRicerca;
import dataview.Ordinamento;
import dataview.PerStringa;
import dataview.PerTermine;
import dataview.TipoTermine;
import exceptions.DBException;
import javax.swing.JButton;

public class Ricerca extends JPanel implements ActionListener {
	private static final long serialVersionUID = 1L;
	private JLabel lTermine = null;
	private JComboBox cbTermine = null;
	private JRadioButton rbStringa = null;
	private JLabel lStringa = null;
	private JTextField tfStringa = null;
	private JRadioButton rbTermine = null;
	private JComboBox cbOrdina = null;
	private List<String> termini; //  @jve:decl-index=0:
	private ButtonGroup bgroup; // @jve:decl-index=0:
	private ButtonGroup bgTermine;
	private ButtonGroup bgStringa;
	private JLabel lCercaStr = null;
	private JLabel lCercaTer = null;
	private JRadioButton rbIsA = null;
	private JRadioButton rbIsNot = null;
	private JRadioButton rbAppare = null;
	private JRadioButton rbNonAppare = null;
	private Tipo tipo = null;
	private Intervalli intervalli = new Intervalli();
	private JTextField genereTF = null; //  @jve:decl-index=0:visual-constraint="391,79"
	private JButton genereB = null; //  @jve:decl-index=0:visual-constraint="543,129"
	private DialogTermine dt;
	private Home home = null;
	
	public enum Tipo {
		CIBI, RICETTE, MENU
	};
	
	/**
	 * This is the default constructor
	 */
	public Ricerca(Tipo tipo, Home home) {
		super();
		this.tipo = tipo;
		this.home = home;
		initialize();
		abilita(false);
	}
	
	public CriterioRicerca getCriterioRicerca() {
		CriterioRicerca criterio = null;
		if (!isEnabled()) return null;
		Ordinamento o = Ordinamento.valueOf(cbOrdina.getSelectedItem().toString());
		do {
			if (rbStringa.isSelected()) {
				String st = tfStringa.getText();
				if (st == null) {
					JOptionPane.showMessageDialog(this, "Inserire una stringa da ricercare", "Attenzione", JOptionPane.WARNING_MESSAGE);
					break;
				}
				if ((!rbAppare.isSelected()) && (!rbNonAppare.isSelected())) {
					JOptionPane.showMessageDialog(this, "Scegliere se comprendere o escludere la stringa dalla ricerca", "Attenzione", JOptionPane.WARNING_MESSAGE);
					break;
				}
				criterio = new PerStringa(o, st, rbAppare.isSelected());
			} else if (rbTermine.isSelected()) {
				if ((tipo != Tipo.CIBI && cbTermine.getSelectedIndex() == 0) || (tipo == Tipo.CIBI && getGenereTF().getText().isEmpty())) {
					JOptionPane.showMessageDialog(this, "Selezionare un termine", "Attenzione", JOptionPane.WARNING_MESSAGE);
					break;
				}
				Termine t = null;
				if (tipo == Tipo.CIBI)
//					t = new Termine(TipoTermine.genere_cibo, cbTermine.getSelectedItem().toString());
				t = new Termine(TipoTermine.genere_cibo, genereTF.getText());
				else if (tipo == Tipo.RICETTE || tipo == Tipo.MENU) {
					TipoTermine tt = intervalli.getTipo(cbTermine.getSelectedIndex());
					if (tt == null) {
						JOptionPane.showMessageDialog(this, "Selezionare un termine valido", "Attenzione", JOptionPane.WARNING_MESSAGE);
						break;
					}
					t = new Termine(tt, cbTermine.getSelectedItem().toString());
				}
				criterio = new PerTermine(o, t, rbIsA.isSelected());
			}
		} while (false);
		return criterio;
	}
	
	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		GridBagConstraints gridBagConstraints11 = new GridBagConstraints();
		gridBagConstraints11.fill = GridBagConstraints.VERTICAL;
		gridBagConstraints11.gridy = 0;
		gridBagConstraints11.weightx = 1.0;
		gridBagConstraints11.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints11.gridx = 1;
		gridBagConstraints11.gridwidth = 2;
		GridBagConstraints gridBagConstraints6 = new GridBagConstraints();
		gridBagConstraints6.gridx = 1;
		gridBagConstraints6.anchor = GridBagConstraints.WEST;
		gridBagConstraints6.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints6.gridwidth = 2;
		gridBagConstraints6.gridy = 12;
		GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
		gridBagConstraints5.gridx = 1;
		gridBagConstraints5.anchor = GridBagConstraints.WEST;
		gridBagConstraints5.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints5.gridwidth = 2;
		gridBagConstraints5.gridy = 9;
		GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
		gridBagConstraints4.gridx = 1;
		gridBagConstraints4.anchor = GridBagConstraints.WEST;
		gridBagConstraints4.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints4.gridwidth = 2;
		gridBagConstraints4.gridy = 5;
		GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
		gridBagConstraints3.gridx = 1;
		gridBagConstraints3.anchor = GridBagConstraints.WEST;
		gridBagConstraints3.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints3.gridwidth = 2;
		gridBagConstraints3.gridy = 4;
		GridBagConstraints gridBagConstraints21 = new GridBagConstraints();
		gridBagConstraints21.gridx = 1;
		gridBagConstraints21.anchor = GridBagConstraints.WEST;
		gridBagConstraints21.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints21.ipadx = 0;
		gridBagConstraints21.gridwidth = 2;
		gridBagConstraints21.gridheight = 1;
		gridBagConstraints21.gridy = 2;
		lCercaTer = new JLabel();
		if (tipo == Tipo.CIBI)
			lCercaTer.setText("Selezionare un tipo di cibo");
		else if (tipo == Tipo.RICETTE)
			lCercaTer.setText("Selezionare un tipo di ricetta");
		else if (tipo == Tipo.MENU) lCercaTer.setText("Selezionare un tipo di menu");
		lCercaTer.setFont(new Font("Dialog", Font.PLAIN, 12));
		GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
		gridBagConstraints1.gridx = 1;
		gridBagConstraints1.anchor = GridBagConstraints.WEST;
		gridBagConstraints1.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints1.gridwidth = 2;
		gridBagConstraints1.gridy = 7;
		lCercaStr = new JLabel();
		lCercaStr.setText("Inserire la stringa");
		lCercaStr.setFont(new Font("Dialog", Font.PLAIN, 12));
		GridBagConstraints gridBagConstraints15 = new GridBagConstraints();
		gridBagConstraints15.gridx = 0;
		gridBagConstraints15.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints15.gridy = 1;
		GridBagConstraints gridBagConstraints14 = new GridBagConstraints();
		gridBagConstraints14.fill = GridBagConstraints.HORIZONTAL;
		gridBagConstraints14.gridy = 8;
		gridBagConstraints14.weightx = 1.0;
		gridBagConstraints14.anchor = GridBagConstraints.WEST;
		gridBagConstraints14.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints14.gridwidth = 2;
		gridBagConstraints14.gridx = 1;
		GridBagConstraints gridBagConstraints10 = new GridBagConstraints();
		gridBagConstraints10.gridx = 1;
		gridBagConstraints10.gridwidth = 2;
		gridBagConstraints10.anchor = GridBagConstraints.WEST;
		gridBagConstraints10.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints10.gridy = 6;
		lStringa = new JLabel();
		lStringa.setText("Ricerca per stringa");
		lStringa.setFont(new Font("Dialog", Font.BOLD, 12));
		GridBagConstraints gridBagConstraints9 = new GridBagConstraints();
		gridBagConstraints9.gridx = 0;
		gridBagConstraints9.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints9.gridy = 6;
		GridBagConstraints gbcTermineCB = new GridBagConstraints();
		gbcTermineCB.fill = GridBagConstraints.HORIZONTAL;
		gbcTermineCB.gridy = 3;
		gbcTermineCB.weightx = 1.0;
		gbcTermineCB.anchor = GridBagConstraints.WEST;
		gbcTermineCB.insets = new Insets(5, 5, 5, 5);
		gbcTermineCB.gridwidth = 2;
		gbcTermineCB.gridx = 1;
		
		GridBagConstraints gbcGenereTF = new GridBagConstraints();
		gbcGenereTF.fill = GridBagConstraints.HORIZONTAL;
		gbcGenereTF.gridy = 3;
		gbcGenereTF.weightx = 1.0;
		gbcGenereTF.anchor = GridBagConstraints.WEST;
		gbcGenereTF.insets = new Insets(5, 5, 5, 5);
		gbcGenereTF.gridx = 1;
		GridBagConstraints gbcGenereButton = new GridBagConstraints();
		gbcGenereButton.fill = GridBagConstraints.HORIZONTAL;
		gbcGenereButton.gridy = 3;
		gbcGenereButton.weightx = 1.0;
		gbcGenereButton.anchor = GridBagConstraints.WEST;
		gbcGenereButton.insets = new Insets(5, 5, 5, 5);
		gbcGenereButton.gridx = 2;
		
		GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
		gridBagConstraints2.gridx = 1;
		gridBagConstraints2.gridwidth = 2;
		gridBagConstraints2.anchor = GridBagConstraints.WEST;
		gridBagConstraints2.insets = new Insets(5, 5, 5, 5);
		gridBagConstraints2.gridy = 1;
		lTermine = new JLabel();
		lTermine.setText("Ricerca per termine");
		lTermine.setFont(new Font("Dialog", Font.BOLD, 12));
		this.setLayout(new GridBagLayout());
		this.setSize(279, 349);
		this.add(lTermine, gridBagConstraints2);
		if (tipo != Tipo.CIBI)
			this.add(getCbTermine(), gbcTermineCB);
		else {
			this.add(getGenereTF(), gbcGenereTF);
			this.add(getGenereB(), gbcGenereButton);
		}
		this.add(getRbStringa(), gridBagConstraints9);
		this.add(lStringa, gridBagConstraints10);
		this.add(getTfStringa(), gridBagConstraints14);
		this.add(getRbTermine(), gridBagConstraints15);
		this.add(lCercaStr, gridBagConstraints1);
		this.add(lCercaTer, gridBagConstraints21);
		this.add(getRbIsA(), gridBagConstraints3);
		this.add(getRbIsNot(), gridBagConstraints4);
		this.add(getRbAppare(), gridBagConstraints5);
		this.add(getRbNonAppare(), gridBagConstraints6);
		this.add(getCbOrdina(), gridBagConstraints11);
		this.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
			public void propertyChange(java.beans.PropertyChangeEvent e) {
				if ((e.getPropertyName().equals("enabled"))) {
					if (e.getNewValue() == Boolean.TRUE)
						abilita(getRbTermine().isSelected());
					else if (e.getNewValue() == Boolean.FALSE) abilitaTutto(false);
				}
			}
		});
		getCbTermine().setEnabled(false);
		bgroup = new ButtonGroup();
		bgroup.add(rbStringa);
		bgroup.add(rbTermine);
		bgTermine = new ButtonGroup();
		bgTermine.add(rbIsA);
		bgTermine.add(rbIsNot);
		bgStringa = new ButtonGroup();
		bgStringa.add(rbAppare);
		bgStringa.add(rbNonAppare);
		dt = new DialogTermine(home, TipoTermine.genere_cibo, true, false);
	}
	
	private void abilita(boolean perTermine) {
		abilitaTutto(true);
		
		cbTermine.setEnabled(perTermine);
		rbIsA.setEnabled(perTermine);
		rbIsNot.setEnabled(perTermine);
		genereB.setEnabled(perTermine);
		lCercaTer.setEnabled(perTermine);
		genereTF.setEnabled(perTermine);
		
		rbNonAppare.setEnabled(!perTermine);
		rbAppare.setEnabled(!perTermine);
		tfStringa.setEditable(!perTermine);
		lCercaStr.setEnabled(!perTermine);
	}
	
	private void abilitaTutto(boolean b) {
		getCbTermine().setEnabled(b);
		rbIsA.setEnabled(b);
		rbIsNot.setEnabled(b);
		rbNonAppare.setEnabled(b);
		rbAppare.setEnabled(b);
		tfStringa.setEnabled(b);
		rbStringa.setEnabled(b);
		rbTermine.setEnabled(b);
		cbOrdina.setEnabled(b);
		lCercaTer.setEnabled(b);
		lCercaStr.setEnabled(b);
		lTermine.setEnabled(b);
		lStringa.setEnabled(b);
		getGenereB().setEnabled(b);
		getGenereTF().setEnabled(b);
	}
	
	public void focus() {
		cbOrdina.requestFocus();
	}
	
	@Override
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == rbStringa)
			abilita(false);
		else if (arg0.getSource() == rbTermine) abilita(true);
	}
	
	/**
	 * This method initializes cbTermine
	 * 
	 * @return javax.swing.JComboBox
	 */
	private JComboBox getCbTermine() {
		if (cbTermine == null) {
			termini = new LinkedList<String>();
			try {
				if (tipo == Tipo.CIBI) {
					termini.add("-- Nessun genere selezionato --");
					termini.addAll(Terminologia.getTerminologia().getTuttiTermini(TipoTermine.genere_cibo));
				}
				//TODO: per ricette e menu
				else if (tipo == Tipo.RICETTE) {
					termini.add("-- Nessun termine selezionato --");
					addTermini(TipoTermine.tipo_preparazione);
					addTermini(TipoTermine.genere_cucina);
					addTermini(TipoTermine.genere_geografico);
				} else if (tipo == Tipo.MENU) {
					termini.add("-- Nessun termine selezionato --");
					addTermini(TipoTermine.tipo_occasione);
					addTermini(TipoTermine.stagionalita);
				}
				cbTermine = new JComboBox(termini.toArray());
				cbTermine.setFont(new Font("Dialog", Font.PLAIN, 12));
			} catch (DBException e) {
				e.printStackTrace();
			}
		}
		return cbTermine;
	}
	
	/**
	 * This method initializes rbStringa
	 * 
	 * @return javax.swing.JRadioButton
	 */
	private JRadioButton getRbStringa() {
		if (rbStringa == null) {
			rbStringa = new JRadioButton();
			rbStringa.addActionListener(this);
			rbStringa.setSelected(true);
		}
		return rbStringa;
	}
	
	/**
	 * This method initializes tfStringa
	 * 
	 * @return javax.swing.JTextField
	 */
	private JTextField getTfStringa() {
		if (tfStringa == null) {
			tfStringa = new JTextField();
			tfStringa.setColumns(20);
			tfStringa.setFont(new Font("Georgia", Font.PLAIN, 12));
		}
		return tfStringa;
	}
	
	/**
	 * This method initializes rbTermine
	 * 
	 * @return javax.swing.JRadioButton
	 */
	private JRadioButton getRbTermine() {
		if (rbTermine == null) {
			rbTermine = new JRadioButton();
			rbTermine.setSelected(false);
			rbTermine.setMnemonic(KeyEvent.VK_UNDEFINED);
			rbTermine.addActionListener(this);
		}
		return rbTermine;
	}
	
	/**
	 * This method initializes cbOrdina
	 * 
	 * @return javax.swing.JComboBox
	 */
	private JComboBox getCbOrdina() {
		if (cbOrdina == null) {
			Set<String> ordine = new TreeSet<String>();
			for (Ordinamento o : Ordinamento.values())
				ordine.add(o.toString());
			cbOrdina = new JComboBox(ordine.toArray());
			cbOrdina.setFont(new Font("Dialog", Font.PLAIN, 12));
		}
		return cbOrdina;
	}
	
	/**
	 * This method initializes rbIsA
	 * 
	 * @return javax.swing.JRadioButton
	 */
	private JRadioButton getRbIsA() {
		if (rbIsA == null) {
			rbIsA = new JRadioButton();
			if (tipo == Tipo.CIBI)
				rbIsA.setText("cercare cibi del tipo selezionato");
			else if (tipo == Tipo.RICETTE)
				rbIsA.setText("cercare ricette con il termine selezionato");
			else if (tipo == Tipo.MENU) rbIsA.setText("cercare menu con il termine selezionato");
			//rbIsA.setFont(new Font("Georgia", Font.BOLD, 12));
			rbIsA.setFont(new Font("Dialog", Font.PLAIN, 12));
			rbIsA.setSelected(true);
			rbIsA.setEnabled(false);
		}
		return rbIsA;
	}
	
	/**
	 * This method initializes rbIsNot
	 * 
	 * @return javax.swing.JRadioButton
	 */
	private JRadioButton getRbIsNot() {
		if (rbIsNot == null) {
			rbIsNot = new JRadioButton();
			rbIsNot.setText("escludere il tipo selezionato dalla ricerca");
			rbIsNot.setFont(new Font("Dialog", Font.PLAIN, 12));
			rbIsNot.setEnabled(false);
		}
		return rbIsNot;
	}
	
	/**
	 * This method initializes rbAppare
	 * 
	 * @return javax.swing.JRadioButton
	 */
	private JRadioButton getRbAppare() {
		if (rbAppare == null) {
			rbAppare = new JRadioButton();
			rbAppare.setText("cercare la stringa inserita");
			rbAppare.setSelected(true);
			rbAppare.setFont(new Font("Dialog", Font.PLAIN, 12));
			rbAppare.setEnabled(true);
		}
		return rbAppare;
	}
	
	/**
	 * This method initializes rbNonAppare
	 * 
	 * @return javax.swing.JRadioButton
	 */
	private JRadioButton getRbNonAppare() {
		if (rbNonAppare == null) {
			rbNonAppare = new JRadioButton();
			rbNonAppare.setText("escludere la stringa dalla ricerca");
			rbNonAppare.setFont(new Font("Dialog", Font.PLAIN, 12));
			rbNonAppare.setEnabled(true);
			rbNonAppare.setSelected(false);
		}
		return rbNonAppare;
	}
	
	private void addTermini(TipoTermine tipo) {
		termini.add("-- " + tipo.toString().toUpperCase().replace("_", " ") + " --");
		int min = termini.size();
		try {
			termini.addAll(Terminologia.getTerminologia().getTuttiTermini(tipo));
			intervalli.add(new Intervallo(min, termini.size() - 1, tipo));
		} catch (DBException e) {
			e.printStackTrace();
		}
	}
	
	private class Intervallo {
		int min, max;
		TipoTermine tipo;
		
		Intervallo(int min, int max, TipoTermine tipo) {
			this.min = min;
			this.max = max;
			this.tipo = tipo;
		}
	}
	
	private class Intervalli extends LinkedList<Intervallo> {
		private static final long serialVersionUID = -5375725968701025667L;
		
		Intervalli() {
			super();
		}
		
		TipoTermine getTipo(int i) {
			for (Intervallo intervallo : this) {
				if (i >= intervallo.min && i <= intervallo.max) return intervallo.tipo;
			}
			return null;
		}
	}
	
	/**
	 * This method initializes genereTF
	 * 
	 * @return javax.swing.JTextField
	 */
	private JTextField getGenereTF() {
		if (genereTF == null) {
			genereTF = new JTextField();
			genereTF.setEditable(false);
		}
		return genereTF;
	}
	
	/**
	 * This method initializes genereB
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getGenereB() {
		if (genereB == null) {
			genereB = new JButton();
			genereB.setText("Seleziona genere");
			genereB.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					dt.setVisible(true);
					if (dt.getTermine() == null)
						getGenereTF().setText("");
					else getGenereTF().setText(dt.getTermine().toString());
				}
			});
		}
		return genereB;
	}
	
} //  @jve:decl-index=0:visual-constraint="0,-19"
